package com.wy.base;

import java.util.List;
import java.util.Map;
import java.util.Objects;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.validation.BindingResult;
import org.springframework.validation.FieldError;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;

import com.alibaba.fastjson.JSON;
import com.wy.annotation.ListModel;
import com.wy.result.Result;
import com.wy.result.ResultException;
import com.wy.utils.ListUtils;
import com.wy.utils.MapUtils;
import com.wy.utils.StrUtils;
import com.wy.valid.ValidCreates;
import com.wy.valid.ValidEdits;

import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

/**
 * @description
 * @author ParadiseWY
 * @date 2019年7月30日 上午11:56:31
 */
public abstract class AbstractCrl<T> {

	@Autowired
	public AbstractService<T> abstractService;

	@ApiOperation("通用单条数据新增")
	@PostMapping("create")
	public Result<?> create(@RequestBody @Validated(ValidCreates.class) T model,
			BindingResult errors) {
		if (errors.hasErrors()) {
			FieldError error = errors.getFieldError();
			return Result.error(error.getField() + error.getDefaultMessage());
		}
		Object res = abstractService.create(model);
		return Objects.nonNull(res) ? Result.ok(res) : Result.error("新增失败");
	}

	@ApiOperation("通用批量数据新增")
	@PostMapping("creates")
	public Result<?> creates(@RequestBody @Validated(ValidCreates.class) List<T> models,
			BindingResult errors) {
		if (errors.hasErrors()) {
			FieldError error = errors.getFieldError();
			return Result.error(error.getField() + error.getDefaultMessage());
		}
		abstractService.creates(models);
		return Result.ok();
	}

	@ApiOperation("当主键类型为字符串时使用该方法删除表中单条数据")
	@GetMapping("removeName/{id}")
	public Result<?> removeName(@PathVariable String id) {
		int row = abstractService.delete(id);
		if (row > 0) {
			return Result.ok(row);
		}
		return Result.error("删除失败");
	}

	@ApiOperation("当主键类型为数字时使用该方法删除表中单条数据")
	@GetMapping("removeId/{id}")
	public Result<?> removeId(@PathVariable Integer id) {
		int row = abstractService.delete(id);
		if (row > 0) {
			return Result.ok(row);
		}
		return Result.error("删除失败");
	}

	@ApiOperation("当主键类型为字符串时使用该方法批量删除表中数据")
	@PostMapping("removeNames")
	public Result<?> removeNames(@RequestBody List<String> Ids) {
		if (ListUtils.isBlank(Ids)) {
			return Result.error("集合数据为空");
		}
		return Result.ok(abstractService.deletes(Ids));
	}

	@ApiOperation("当主键类型为数字时使用该方法批量删除表中数据")
	@PostMapping("removeIds")
	public Result<?> removeIds(@RequestBody List<Integer> Ids) {
		if (ListUtils.isBlank(Ids)) {
			return Result.error("集合数据为空");
		}
		return Result.ok(abstractService.deletes(Ids));
	}

	@ApiOperation("根据主键更新表中的该条数据的全部字段,若是传null,则数据库中字段就为null")
	@PostMapping("edit")
	public Result<?> edit(@RequestBody @Validated(ValidEdits.class) T model, BindingResult errors) {
		if (errors.hasErrors()) {
			FieldError error = errors.getFieldError();
			return Result.error(error.getField() + error.getDefaultMessage());
		}
		return Result.ok(abstractService.modify(model));
	}

	@ApiOperation("查询该类中某个字段值是否重复,若有多个键值对,则只要有一个键值对中值重复,返回false")
	@PostMapping("hasValue")
	public Result<?> hasValue(@RequestBody Map<String, Object> params) {
		if (MapUtils.isBlank(params)) {
			return Result.error("参数为空");
		}
		for (Map.Entry<String, Object> entry : params.entrySet()) {
			if (StrUtils.isNotBlank(entry.getKey())) {
				if (abstractService.hasValue(entry.getKey(), entry.getValue())) {
					return Result.ok(entry.getKey() + "字段值重复", 1);
				}
			}
		}
		return Result.ok("无重复值", 0);
	}

	@ApiOperation("当主键编号为字符串时用该方法获得数据详情")
	@GetMapping("getByName/{id}")
	public Result<?> getByName(@ApiParam("字符串主键编号") @PathVariable String id) {
		return Result.ok(abstractService.getById(id));
	}

	@ApiOperation("当主键编号为数字时用该方法获得数据详情")
	@GetMapping("getById/{id}")
	public Result<?> getById(@ApiParam("数字主键编号") @PathVariable Integer id) {
		return Result.ok(abstractService.getById(id));
	}

	@ApiOperation("查询单个表属性所有数据或分页数据,除分页参数,其他参数不可带")
	@GetMapping("getEntitys")
	public Result<?> getEntitys(@ApiParam("该API实体类参数") T model) {
		return abstractService.getEntitys(model);
	}

	@ApiOperation("查询单个表属性所有数据或分页数据,可带参数")
	@GetMapping("getPage")
	public Result<?> getPage(@ApiParam("该API实体类参数") @RequestParam Map<String, Object> params) {
		return abstractService.getList(params);
	}

	@ApiOperation("复杂分页查询,多表链接")
	@GetMapping("getList")
	public Result<?> getList(
			@ApiParam("该API实体类参数") @RequestParam(required = false) Map<String, Object> params) {
		if (this.getClass().isAnnotationPresent(ListModel.class)) {
			ListModel listModel = this.getClass().getAnnotation(ListModel.class);
			Class<? extends AbstractPage> listClass = listModel.value();
			try {
				if (MapUtils.isBlank(params)) {
					return abstractService.getList(listClass.newInstance());
				} else {
					return abstractService.getList(
							JSON.parseObject(JSON.toJSONString(params), listClass));
				}
			} catch (InstantiationException | IllegalAccessException e) {
				e.printStackTrace();
			}
			return Result.error();
		} else {
			throw new ResultException("该controller没有相应注解可以使用分页方法");
		}
	}
}